<!-- 
  Cascader 级联选择组件                 zls-2023/07/28
    所有属性、事件、方法、插槽，请参考    https://vant-contrib.gitee.io/vant/#/zh-CN/cascader
  
  Demo
    <Form ref="formRef">
      <z-cascader v-model="form.cascader1" label="cascader级联" :options="cascaderOptions1"></z-cascader>
      <z-cascader v-model="form.cascader2" label="cascader级联回选" required :options="cascaderOptions2"></z-cascader>
    </Form>

    const form = reactive({
      cascader1: { text: '', value: null },
      cascader2: { text: '', value: ['320000', '320200'] },
    })

    // cascader级联选择
    const cascaderOptions1 = reactive([
      {
        text: '浙江省',
        value: '330000',
        children: [{ text: '杭州市', value: '330100' }]
      },
      {
        text: '江苏省',
        value: '320000',
        children: [{ text: '南京市', value: '320100' }]
      }
    ])
    const cascaderOptions2 = reactive([
      {
        text: '安徽省',
        value: '330000',
        children: [
          { text: '合肥市', value: '330100' },
          { text: '滁州市', value: '330200' }
        ]
      },
      {
        text: '江苏省',
        value: '320000',
        children: [
          { text: '南京市', value: '320100' },
          { text: '苏州市', value: '320200' }
        ]
      }
    ])
 -->
<template>
  <z-input
    v-bind="{ ...attrsFieldDefault, ...$attrs, modelValue: inputVal }"
    :rules="$attrs['required'] || $attrs['required'] === '' ? [{ required: true, message: '请选择' }] : []"
    @click="show = true"
  >
    <template #right-icon>
      <z-svg name="chahao" v-if="inputVal" @click.stop="clear"></z-svg>
    </template>
  </z-input>
  <Popup v-model:show="show" v-bind="{ ...attrsPopupDefault, ...$attrs }" @click-overlay="show = false" @click-close-icon="show = false">
    <Cascader
      v-model="value"
      :title="$attrs['title'] || '标题'"
      :options="$attrs['options']"
      :placeholder="$attrs['placeholder']"
      :active-color="$attrs['active-color']"
      :swipeable="$attrs['swipeable']"
      :closeable="$attrs['closeable']"
      :field-names="$attrs['field-names']"
      :show-header="$attrs['show-header']"
      :close-icon="$attrs['close-icon']"
      @finish="finish"
      @close="show = false"
    />
  </Popup>
</template>

<script>
export default { name: 'z-cascader' }
</script>
<script setup>
import { ref, useAttrs, watch } from 'vue'
import { Popup, Cascader } from 'vant'
const emit = defineEmits(['update:modelValue', 'clear', 'finish'])
const attrs = useAttrs()

// Field输入框默认属性
const attrsFieldDefault = {
  readonly: true,
  placeholder: '请选择',
  'is-link': true,
  maxlength: '2000'
}
// Popup弹框默认属性
const attrsPopupDefault = {
  position: 'bottom',
  round: true
}

const show = ref(false) // 是否显示弹框
const inputVal = ref('') // 输入框的值
const value = ref('') // 回选值，与options属性中的value对应，清空是置空

// 监听Field输入框值及Cascader绑定值的变化
watch(
  () => JSON.parse(JSON.stringify(attrs.modelValue)),
  (newVal, oldVal) => {
    inputVal.value = newVal.text
    value.value = newVal.value ? newVal.value[newVal.value.length - 1] : ''
  },
  { immediate: true }
)

// 当有默认值时，回选
const textArr = []
setDefaultValue(attrs.modelValue.value)
function setDefaultValue(list) {
  if (!list?.length) return
  backCascader(attrs.options, list)
  inputVal.value = textArr.join(',')
  emit('update:modelValue', { text: textArr.join(','), value: list })
}

// 递归，根据code找到对应的文本内容
function backCascader(arr, codeArr) {
  arr.forEach(v => {
    if (codeArr.indexOf(v.value) !== -1) {
      textArr.push(v.text)
    }
    if (v.children) backCascader(v.children, codeArr)
  })
}

// 清空
function clear() {
  emit('update:modelValue', { text: '', value: null })
  emit('clear', { text: '', value: null })
}

// 选中某一项后，点击确认按钮 { value: 前选中的时间 }
function finish({ value, selectedOptions, tabIndex }) {
  show.value = false
  let valueArr = [],
    textStr = ''
  selectedOptions.forEach(v => {
    textStr += `${v.text},`
    valueArr.push(v.value)
  })
  textStr = textStr.slice(0, -1)
  emit('update:modelValue', { text: textStr, value: valueArr })
  emit('finish', { text: textStr, value: valueArr })
}
</script>
